package dou.net.protocol;

import com.google.protobuf.GeneratedMessageV3;
import dou.net.socket.IClientSocket;

/**
 * 为消息处理提供一个独立的线程进行处理
 * @author wizardc
 */
public abstract class AbstractHandlerRunnable implements Runnable
{
    /**
     * 消息 ID
     */
    protected int _msgID;

    /**
     * 消息流水号
     */
    protected int _msgNum;

    /**
     * 消息数据
     */
    protected byte[] _bytes;

    /**
     * 消息结构体
     */
    protected GeneratedMessageV3 _message;

    /**
     * 发送消息的客户端套接字对象
     */
    protected IClientSocket _socket;

    /**
     * 协议对象
     */
    protected IProtocol _protocol;

    /**
     * 构造函数
     * @param msgID 消息 ID
     * @param msgNum 消息流水号
     * @param bytes 消息数据
     * @param socket 发送消息的客户端套接字对象
     * @param protocol 协议对象
     */
    public AbstractHandlerRunnable(int msgID, int msgNum, byte[] bytes, IClientSocket socket, IProtocol protocol)
    {
        _msgID = msgID;
        _msgNum = msgNum;
        _bytes = bytes;
        _socket = socket;
        _protocol = protocol;
    }

    /**
     * 构造函数
     * @param msgID 消息 ID
     * @param msgNum 消息流水号
     * @param message 消息结构体
     * @param socket 发送消息的客户端套接字对象
     * @param protocol 协议对象
     */
    public AbstractHandlerRunnable(int msgID, int msgNum, GeneratedMessageV3 message, IClientSocket socket, IProtocol protocol)
    {
        _msgID = msgID;
        _msgNum = msgNum;
        _message = message;
        _socket = socket;
        _protocol = protocol;
    }

    @Override
    public void run()
    {
        try
        {
            if(_message == null)
            {
                _message = this.parseMessage(_msgID, _bytes);
            }
            IMessageHandler messageHandler = _protocol.getMessageHandler(_msgID);
            if(messageHandler != null)
            {
                messageHandler.messageHandler(_msgID, _msgNum, _message, _socket);
            }
            else
            {
                errorHandler("Protocol \"" + getClass().getName() + "\" handler error: No msgID \"" + _msgID + "\"", null);
            }
        }
        catch(Exception exception)
        {
            errorHandler("Protocol \"" + getClass().getName() + "\" handler error: ", exception);
        }
    }

    /**
     * 错误处理
     * @param errorStr 错误信息
     * @param exception 异常对象
     */
    protected abstract void errorHandler(String errorStr, Exception exception);

    /**
     * 解析消息流为对应的消息对象
     * @param msgID 消息方法 ID
     * @param bytes 消息数据
     * @return 消息对象
     * @throws Exception 解析错误时抛出该异常
     */
    protected abstract GeneratedMessageV3 parseMessage(int msgID, byte[] bytes) throws Exception;
}
